export const isFalsy = (val: unknown) => (val === 0 ? true : !val);
export const isVoid = (val: unknown) =>
  val === undefined || val === null || val === "";

export const pureObject = (
  obj: Record<string, unknown>,
  cb: (v: unknown) => boolean = isVoid
) => {
  const result = { ...obj };

  Object.entries(result).forEach(([k, v]) => {
    if (cb(v)) delete result[k];
  });

  return result;
};

export const urlStringfy = (
  obj: Record<string, unknown> = {},
  prefix: boolean = false
) => {
  const newObj = pureObject(obj);

  const result = Object.entries(newObj)
    .map(([k, v]) => `${k}=${v}`)
    .join("&");

  return result ? (prefix ? `?${result}` : result) : "";
};

export const getUrlParams = (url: string) => {
  const params = url.split("?")[1];
  if (!params) return {};

  return params
    .split("&")
    .filter(Boolean)
    .reduce<Record<string, unknown>>((prev, cur) => {
      const [k, v] = cur.split("=") || [];
      prev[k] = v;
      return prev;
    }, {});
};

export const formatDate = (date: Date | number): string => {
  date = new Date(date);
  const YY = date.getFullYear() + "-";
  const MM =
    (date.getMonth() + 1 < 10
      ? "0" + (date.getMonth() + 1)
      : date.getMonth() + 1) + "-";
  const DD = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
  const hh =
    (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
  const mm =
    (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) +
    ":";
  const ss =
    date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
  return YY + MM + DD + " " + hh + mm + ss;
};

export function curry<A1>(fn: (params: A1) => void, ...args1: A1[]) {
  return function curriedFn<A2 extends A1>(...args2: A2[]) {
    if (args2.length < fn.length) {
      return function <A3 extends A2 & A1>(...args3: A3[]) {
        return curriedFn(...args1, ...args2, ...args3);
      };
    }

    // @ts-ignore
    return fn(...args1, ...args2);
  };
}
